wayland: Implement gdk_screen_get_monitor_scale()
authorAlexander Larsson <alexl@redhat.com>
Tue, 4 Jun 2013 09:18:49 +0000 (11:18 +0200)
committerAlexander Larsson <alexl@redhat.com>
Wed, 3 Jul 2013 12:34:13 +0000 (14:34 +0200)
We bind to the newer version of the wl_output which supports
the new done and scale events, and if we use this to get the
scale for each monitor (defaulting to 1 if not supported).

gdk/wayland/gdkdisplay-wayland.c
gdk/wayland/gdkprivate-wayland.h
gdk/wayland/gdkscreen-wayland.c

index ee51ab57cae352a98eab6f6f16f37070de4127fe..dec350a0a569bc10bda2faf4b37fc42a84cb6770 100644 (file)
@@ -168,8 +168,8 @@ gdk_registry_handle_global(void *data, struct wl_registry *registry, uint32_t id
        wl_registry_bind(display_wayland->wl_registry, id, &wl_shell_interface, 1);
   } else if (strcmp(interface, "wl_output") == 0) {
     output =
-      wl_registry_bind(display_wayland->wl_registry, id, &wl_output_interface, 1);
-    _gdk_wayland_screen_add_output(display_wayland->screen, id, output);
+      wl_registry_bind(display_wayland->wl_registry, id, &wl_output_interface, 2);
+    _gdk_wayland_screen_add_output(display_wayland->screen, id, output, version);
     /* We need another roundtrip to receive the modes and geometry
      * events for the output, which gives us the physical properties
      * and available modes on the output. */
index 43d1c3d93d4875228c365505982000dafbae9b48..ebe4f43bd4c88b3d600c797a43dbe0bc8013d1fd 100644 (file)
@@ -161,11 +161,14 @@ GdkWindow *_gdk_wayland_screen_create_root_window (GdkScreen *screen,
 GdkScreen *_gdk_wayland_screen_new (GdkDisplay *display);
 void _gdk_wayland_screen_add_output (GdkScreen        *screen,
                                      guint32           id,
-                                     struct wl_output *output);
+                                     struct wl_output *output,
+                                    guint32           version);
 void _gdk_wayland_screen_remove_output (GdkScreen *screen,
                                         guint32 id);
 int _gdk_wayland_screen_get_output_refresh_rate (GdkScreen        *screen,
                                                  struct wl_output *output);
+guint32 _gdk_wayland_screen_get_output_scale (GdkScreen        *screen,
+                                             struct wl_output *output);
 
 void _gdk_wayland_window_set_device_grabbed (GdkWindow      *window,
                                              GdkDevice      *device,
index a081e1147064d7231dd30090224adc699829ba02..7fa9add75512a6f9896bdbe325c44454a541e882 100644 (file)
@@ -77,10 +77,13 @@ struct _GdkWaylandScreenClass
   void (* window_manager_changed) (GdkWaylandScreen *screen_wayland);
 };
 
+#define OUTPUT_VERSION_WITH_DONE 2
+
 struct _GdkWaylandMonitor
 {
   GdkWaylandScreen *screen;
   guint32       id;
+  guint32       version;
   struct wl_output *output;
   GdkRectangle  geometry;
   int          width_mm;
@@ -88,6 +91,7 @@ struct _GdkWaylandMonitor
   char *       output_name;
   char *       manufacturer;
   int          refresh_rate;
+  gint          scale;
 };
 
 G_DEFINE_TYPE (GdkWaylandScreen, _gdk_wayland_screen, GDK_TYPE_SCREEN)
@@ -249,6 +253,21 @@ gdk_wayland_screen_get_monitor_geometry (GdkScreen    *screen,
     *dest = monitor->geometry;
 }
 
+static gint
+gdk_wayland_screen_get_monitor_scale_factor (GdkScreen *screen,
+                                            gint       monitor_num)
+{
+  GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
+  GdkWaylandMonitor *monitor;
+
+  if (monitor_num >= screen_wayland->monitors->len)
+    return 1;
+
+  monitor = g_ptr_array_index(screen_wayland->monitors, monitor_num);
+
+  return monitor->scale;
+}
+
 static GdkVisual *
 gdk_wayland_screen_get_system_visual (GdkScreen * screen)
 {
@@ -822,6 +841,7 @@ _gdk_wayland_screen_class_init (GdkWaylandScreenClass *klass)
   screen_class->get_monitor_plug_name = gdk_wayland_screen_get_monitor_plug_name;
   screen_class->get_monitor_geometry = gdk_wayland_screen_get_monitor_geometry;
   screen_class->get_monitor_workarea = gdk_wayland_screen_get_monitor_geometry;
+  screen_class->get_monitor_scale_factor = gdk_wayland_screen_get_monitor_scale_factor;
   screen_class->get_system_visual = gdk_wayland_screen_get_system_visual;
   screen_class->get_rgba_visual = gdk_wayland_screen_get_rgba_visual;
   screen_class->is_composited = gdk_wayland_screen_is_composited;
@@ -888,13 +908,33 @@ output_handle_geometry(void *data,
   monitor->manufacturer = g_strdup (make);
   monitor->output_name = g_strdup (model);
 
-  if (monitor->geometry.width != 0)
+  if (monitor->geometry.width != 0 && monitor->version < OUTPUT_VERSION_WITH_DONE)
     {
       g_signal_emit_by_name (monitor->screen, "monitors-changed");
       update_screen_size (monitor->screen);
     }
 }
 
+static void
+output_handle_done(void *data,
+                  struct wl_output *wl_output)
+{
+  GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)data;
+
+  g_signal_emit_by_name (monitor->screen, "monitors-changed");
+  update_screen_size (monitor->screen);
+}
+
+static void
+output_handle_scale(void *data,
+                   struct wl_output *wl_output,
+                   uint32_t factor)
+{
+  GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)data;
+
+  monitor->scale = factor;
+}
+
 static void
 output_handle_mode(void *data,
                    struct wl_output *wl_output,
@@ -912,27 +952,35 @@ output_handle_mode(void *data,
   monitor->geometry.height = height;
   monitor->refresh_rate = refresh;
 
-  g_signal_emit_by_name (monitor->screen, "monitors-changed");
-  update_screen_size (monitor->screen);
+  if (monitor->geometry.width != 0 && monitor->version < OUTPUT_VERSION_WITH_DONE)
+    {
+      g_signal_emit_by_name (monitor->screen, "monitors-changed");
+      update_screen_size (monitor->screen);
+    }
 }
 
 static const struct wl_output_listener output_listener =
 {
   output_handle_geometry,
-  output_handle_mode
+  output_handle_mode,
+  output_handle_done,
+  output_handle_scale,
 };
 
 void
 _gdk_wayland_screen_add_output (GdkScreen        *screen,
                                 guint32           id,
-                                struct wl_output *output)
+                                struct wl_output *output,
+                               guint32           version)
 {
   GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
   GdkWaylandMonitor *monitor = g_new0(GdkWaylandMonitor, 1);
 
   monitor->id = id;
   monitor->output = output;
+  monitor->version = version;
   monitor->screen = screen_wayland;
+  monitor->scale = 1;
   g_ptr_array_add(screen_wayland->monitors, monitor);
 
   wl_output_add_listener(output, &output_listener, monitor);
@@ -977,3 +1025,21 @@ _gdk_wayland_screen_get_output_refresh_rate (GdkScreen        *screen,
 
   return 0;
 }
+
+guint32
+_gdk_wayland_screen_get_output_scale (GdkScreen        *screen,
+                                     struct wl_output *output)
+{
+  GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
+  int i;
+
+  for (i = 0; i < screen_wayland->monitors->len; i++)
+    {
+      GdkWaylandMonitor *monitor = screen_wayland->monitors->pdata[i];
+
+      if (monitor->output == output)
+        return monitor->scale;
+    }
+
+  return 0;
+}